一直想系统地学习Android源码,最近又计划写一个自定义控件系列的博客,而在自定义控件的过程中,许多技巧和方法需要你在Android View,ViewGroup的源码中得到灵感。因此,这一个View的22500行源码分析系列就诞生了,本系列基于api23的View的源码,主要是对源码的注解作一些翻译和简单的总结,目的是让大家了解整个View的工
作流程,一些主要方法实现里面的细节问题。说时迟那时快,老司机开车啦,赶紧上车
首先我们看一下View常用的几个方法:
@RemotableViewMethod
public void setVisibility(@Visibility int visibility) {
setFlags(visibility, VISIBILITY_MASK);
}
public void setFocusable(boolean focusable) { if (!focusable) { setFlags(0, FOCUSABLE_IN_TOUCH_MODE); } setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK); }
public void setEnabled(boolean enabled) { if (enabled == isEnabled()) return; setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK); /* * The View most likely has to change its appearance, so refresh * the drawable state.
视图大多数可能改变它的样子,所以刷新drawable的状态 */ refreshDrawableState(); // Invalidate too, since the default behavior for views is to be // be drawn at 50% alpha rather than to change the drawable.
//同时也要刷新,因为默认的View enable为false的行为是透明度为原来的50%而不是改变drawable invalidate(true); if (!enabled) { cancelPendingInputEvents(); } }
兄弟们,看见没,看见没!这三个方法里面都会调用关键的setFlags()方法,这方法到底是何方神圣!让我们慢慢揭开其神秘的面纱吧
/*** Set flags controlling behavior of this view.*设置标记来控制视图的状态** @param flags Constant indicating the value which should be set 表示应该要被设置的值常量* @param mask Constant indicating the bit range that should be changed 表示应该要被改变的位的常量*/该函数在View中多处被调用,例如 View.setEnable()、View.setClickable(),setFocusable()等很多函数都调用到该函数。在View中使用mViewFlags和mPrivateFlags变量保存大多数的属性:– mViewFlags:该标记用来保存和视图状态相关的属性。– mPrivateFlags 该标记用来保存和内部逻辑相关的属性如Visible相关的Flag:public static final int VISIBLE = 0x00000000; public static final int INVISIBLE = 0x00000004; public static final int GONE = 0x00000008; static final int VISIBILITY_MASK = 0x0000000C;
void setFlags(int flags, int mask) {final boolean accessibilityEnabled =AccessibilityManager.getInstance(mContext).isEnabled();final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
int old = mViewFlags;//记录原来的视图状态标记mViewFlags = (mViewFlags & ~mask) | (flags & mask);//更新视图状态标记
int changed = mViewFlags ^ old;//异或判断状态是否发生改变if (changed == 0) {//如果没有改变,立刻返回return;}int privateFlags = mPrivateFlags;//记录当前逻辑属性标记
/* Check if the FOCUSABLE bit has changed */ 检查Focusable位有没有改变if (((changed & FOCUSABLE_MASK) != 0) &&